package server

import (
	"bytes"
	"gitee.com/snxamdf/wui/logs"
	"gitee.com/snxamdf/wui/util"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/url"
)

var (
	controllerMapper = make(map[string]ctl)
)

type ctl struct {
	authorize bool
	cb        func(Context)
}

type result struct {
	Succ bool        `json:"success"`
	Code int         `json:"code"`
	Data interface{} `json:"data"`
}

type Response struct {
	isWrite            bool //是否可以响应输出流 true可以 false不可以
	httpResponseWriter http.ResponseWriter
}

type Html struct {
	tplName string
	data    interface{}
}

type Controller struct {
	result    *result
	responose *Response
	request   *http.Request
	stateCode int
	html      *Html
	cookie    *cookie
}

func (m *result) Success() {
	m.Succ = true
}

func (m *result) Fail() {
	m.Succ = false
}

func (m *Response) Write(data []byte) {
	if m.isWrite {
		m.isWrite = false
		_, _ = m.httpResponseWriter.Write(data)
	}
}

func (m *Html) Data(data interface{}) {
	m.data = data
}

func (m *Controller) TplHtml(tplName string) *Html {
	if tplName[0:1] != "/" {
		tplName = "/" + tplName
	}
	m.html = &Html{
		tplName: tplName,
	}
	return m.html
}

func (m *Controller) toJson() []byte {
	jsonStr, err := util.ToJson(&m.result)
	if err != nil {
		logs.Error("生成json字符串错误", err)
		return []byte(`{"code":"911","data":""}`)
	}
	return jsonStr
}

func (m *Controller) SetCookie(key, value string) {
	setCookie(m.responose.httpResponseWriter, key, value)
}

func (m *Controller) Cookie() Cookie {
	m.cookie = &cookie{
		r: m.request,
		w: m.responose.httpResponseWriter,
	}
	return m.cookie
}

func (m *Controller) write() {
	if m.responose.isWrite {
		m.responose.httpResponseWriter.Header().Set("Content-Type", "application/json")
		if m.stateCode == 0 {
			m.responose.httpResponseWriter.WriteHeader(200)
		} else {
			m.responose.httpResponseWriter.WriteHeader(m.stateCode)
		}
		m.responose.Write(m.toJson())
	}
}

func (m *Controller) StateCode(stateCode int) {
	m.stateCode = stateCode
}

func (m *Controller) Result(code int, data interface{}) Result {
	var result = &result{
		Succ: true,
		Code: code,
		Data: data,
	}
	m.result = result
	return result
}

func (m *Controller) Response() *Response {
	return m.responose
}

func (m *Controller) Request() *http.Request {
	return m.request
}

func (m *Controller) Param(key string) string {
	var val string
	val = m.request.URL.Query().Get(key)
	if val == "" {
		if m.Form() == nil {
			m.request.ParseForm()
		}
		val = m.Form().Get(key)
		if val == "" {
			val = m.PostForm().Get(key)
		}
	}
	return val
}

func (m *Controller) GetFormFile(key string) (multipart.File, *multipart.FileHeader, error) {
	return m.request.FormFile(key)
}

func (m *Controller) Form() url.Values {
	return m.request.Form
}

func (m *Controller) PostForm() url.Values {
	return m.request.PostForm
}

func (m *Controller) GetBody() string {
	result, err := ioutil.ReadAll(m.request.Body)
	if err != nil {
		logs.Error("获取Body数据失败:", err)
		return "{}"
	} else {
		return bytes.NewBuffer(result).String()
	}
}

func (m *Controller) Session() Session {
	sid := getSessionId(m.responose.httpResponseWriter, m.request)
	if session := GetSession(sid); session != nil {
		return session
	} else {
		return createSession(m.responose.httpResponseWriter, m.request)
	}
}

//登录或授权成功后调用，设置已授权
func (m *Controller) LoginAuth() {
	m.Session().auth()
}

//url接口地址
//controller 回调函数 Context 入参上下文
//authorize 是否需要授权访问 true=授权之后才能访问 false=不需要授权
func Route(url string, cb func(Context), authorize bool) {
	logs.Debug("添加 route:", url)
	controllerMapper[url] = ctl{authorize: authorize, cb: cb}
}
